home *** CD-ROM | disk | FTP | other *** search
- /**
- GRAB Graph Layout and Browser System
-
- Copyright (c) 1986, 1988 Regents of the University of California
- Copyright (c) 1989, Tera Computer Company
- **/
-
- /**
- misc.c -- miscellaneous routines: various interfaces
- for redrawing and laying out the graph, plus the Quit routine
- **/
-
- #include "malloc.h"
- #include <stdio.h>
- #include <time.h>
-
- #include "attribute.h"
- #include "digraph.h"
- #include "screen.h"
- #include "globals.h"
- #include "scrdep.h"
- #include "interf.h"
- #include "cursor.h"
-
- void GetSBounds();
- void DoGraph();
-
- static BOOL layed_out = FALSE;
-
- BOOL ReadIn()
- /**
- Read a graph from a file. Keep a record if it was layed out.
- Return true if the graph was actually read.
- **/
- {
- char *buf;
- FILE *graph_file;
- BOOL okay = FALSE;
- DIGRAPH *InitDigraph();
-
- IChangeStatusLine("Reading in graph", TRUE);
- ISetCursor(waitC);
-
- digraph = InitDigraph();
- graphChanged = FALSE;
- ckpt_done = FALSE;
-
- if (*name != '\0' && (graph_file = fopen(name, "r")) != NULL)
- {
- okay = TRUE;
- layed_out = read_graph(digraph, graph_file);
- fclose(graph_file);
- }
- else if (*name != '\0')
- {
- buf = (char *) malloc(MAXLINE * sizeof(char));
- sprintf(buf, "Couldn't open %s", name);
- IChangeStatusLine(buf, FALSE);
- dispose(buf);
- }
- else
- {
- IChangeStatusLine("No file to read", FALSE);
- }
-
- if (NNodeAttr(digraph) == 0)
- /* if no digraph read, give some default attributes */
- {
- char **attr;
-
- attr = (char **) malloc(sizeof(char *));
- strsave(attr[0], "label");
- InitNodeAttrs(digraph, attr, 1, 0);
-
- /* have to make separate space for edge attributes */
- attr = (char **) malloc(sizeof(char *));
- strsave(attr[0], "label");
- InitEdgeAttrs(digraph, attr, 1, 0);
- }
-
- IUnsetCursor();
- return okay;
- }
-
- DisplayReadGraph()
- /**
- we've just called ReadIn. Lay out the graph if need be.
- Then display it
- **/
- {
- if (digraph->lastnode != -1) /* there are nodes to draw */
- {
- if (!layed_out)
- {
- IChangeStatusLine("Laying out graph", TRUE);
- ISetCursor(waitC);
- FixUp();
- }
- else
- {
- IChangeStatusLine("Drawing graph", TRUE);
- ISetCursor(waitC);
- }
- }
-
- DisplayNewGraph();
- IUnsetCursor();
- }
-
- DisplayNewGraph()
- /**
- We've read a new graph, so display it. Then show the graph name,
- the file name, set up the graph attributes window, set up the
- pan and zoom gradients
- **/
- {
- int a, b, c, d, e, f, width, height;
-
- StartDisp();
- IChangeGraphName(Title(digraph));
- IChangeFileName(name);
- ISetAttrNames(digraph->node_att_names, digraph->edge_att_names,
- NNodeAttr(digraph), NEdgeAttr(digraph));
- IGetBounds(&a, &b, &c, &d, &e, &f, &width, &height);
- IChangeZGrad(zoomGradient);
- IChangePGrad((int) (panGradient * width), (int) (panGradient * height));
- }
-
- write_out()
- /* write the digraph to a file */
- {
- FILE *graph_file;
- char *buf;
-
- if (digraph == NULL)
- {
- IChangeStatusLine("No digraph to save", FALSE);
- return;
- }
-
- if ((graph_file = fopen(name, "w")) == NULL)
- {
- buf = (char *) malloc(sizeof(char) * MAXLINE);
- sprintf(buf, "Can't write to %s", name);
- IChangeStatusLine(buf, FALSE);
- dispose(buf);
- return;
- }
-
- IChangeStatusLine("Writing out graph", TRUE);
- write_graph(digraph, graph_file);
-
- fclose(graph_file);
-
- IChangeStatusLine("Done", FALSE);
- graphChanged = FALSE; /* graph written out, so change flag */
- }
-
- FixUp()
- /* layout the graph */
- {
- long clock;
-
- if (digraph == NULL)
- {
- return;
- }
-
- if (printLayoutTime)
- {
- clock = time(NULL);
- printf("time before layout: %s", ctime(&clock));
- }
-
- make_proper(digraph);
-
- if (stopInLayout == STOP_AFTER_MAKEPROPER)
- {
- quick_layout_levels(digraph);
- goto leave;
- }
-
- minimize_crossings(digraph);
-
- if (stopInLayout == STOP_AFTER_MIN_CROSSING)
- {
- quick_layout_levels(digraph);
- goto leave;
- }
-
- layout_levels(digraph);
-
- leave:
- if (printLayoutTime)
- {
- clock = time(0);
- printf("time after layout: %s", ctime(&clock));
- }
- }
-
- StartDisp()
- /**
- display the graph centered in the graph area. No need to do all
- the extra hoohah for a new graph because it isn't one.
- Set up the fonts, too.
- **/
- {
- long clock;
-
- IInitFonts();
-
- FindRange(digraph, &screen.absview);
- MakeMinAbsview(&screen.absview);
-
- ICenterGraph();
- DoGraph();
-
- if (printLayoutTime)
- {
- clock = time(0);
- printf("time after display: %s", ctime(&clock));
- }
- }
-
- /* Make sure the absview covers only the necessary area */
- MakeMinAbsview(absview)
- BOX *absview;
- {
- int xCenter, yCenter;
-
- if (absview->max_x - absview->min_x < MIN_ABS_X_SIZE &&
- absview->max_y - absview->min_y < MIN_ABS_Y_SIZE)
- {
- xCenter = ((absview->max_x - absview->min_x) / 2) + absview->min_x;
- absview->min_x = xCenter - (MIN_ABS_X_SIZE / 2);
- absview->max_x = xCenter + (MIN_ABS_X_SIZE / 2);
-
- yCenter = ((absview->max_y - absview->min_y) / 2) + absview->min_y;
- absview->min_y = yCenter - (MIN_ABS_Y_SIZE / 2);
- absview->max_y = yCenter + (MIN_ABS_Y_SIZE / 2);
- }
- }
-
- /* return the size of the screen */
- void GetSBounds (x0, y0, width, height)
- int *x0, *y0, *width, *height;
- {
- *x0 = screen.canvas.min_x - BORDER_SIZE;
- *y0 = screen.canvas.min_y - BORDER_SIZE;
- *width = screen.canvas.max_x - *x0 + BORDER_SIZE;
- *height = screen.canvas.max_y - *y0 + BORDER_SIZE;
- }
-
- /**
- set up the screen variable to match the canvas and perspective
- for the graph area
- **/
- ReCalcScreen()
- {
- int curx, cury, curwidth, curheight, x0, y0, width, height;
-
- IGetBounds(&x0, &y0, &width, &height, &curx, &cury, &curwidth, &curheight);
-
- screen.display.min_x = curx;
- screen.display.min_y = cury;
- screen.display.max_x = curx + curwidth;
- screen.display.max_y = cury + curheight;
-
- /* leave a little margin */
- screen.canvas.min_x = x0 + BORDER_SIZE;
- screen.canvas.min_y = y0 + BORDER_SIZE;
- screen.canvas.max_x = x0 + width - BORDER_SIZE;
- screen.canvas.max_y = y0 + height - BORDER_SIZE;
-
- /* set up the zoom factors */
- screen.zoom.xzoom = (float) (screen.absview.max_x - screen.absview.min_x) /
- (float) (screen.canvas.max_x - screen.canvas.min_x);
- screen.zoom.yzoom = (float) (screen.absview.max_y - screen.absview.min_y) /
- (float) (screen.canvas.max_y - screen.canvas.min_y);
-
- /* find what part of the absview is visible on the screen */
- screen.bound.min_x = SCRX_TO_ABSX(&screen, 0);
- screen.bound.min_y = SCRY_TO_ABSY(&screen, 0);
- screen.bound.max_x = SCRX_TO_ABSX(&screen, curwidth);
- screen.bound.max_y = SCRY_TO_ABSY(&screen, curheight);
- }
-
- void DoQuit()
- {
- /* graph hasn't changed, so we just leave */
- if (graphChanged == FALSE)
- {
- exit(0);
- }
-
- /* else we ask the user if he really wants to quit */
- if (IConfirm("No write since last change. Quit anyway?") == 'y')
- {
- exit(0);
- }
- }
-